package com.guanghua.brick.html.accessory;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.guanghua.brick.html.Constant;
import com.guanghua.brick.html.tag.WebAppContextTag;
import com.guanghua.brick.util.BeanUtil;
import com.guanghua.brick.util.FileUtil;

public class AccessoryServlet extends HttpServlet {
	
	private static Log logger = LogFactory.getLog(AccessoryServlet.class);
	
	//存放css的缓存
	private HashMap<String, byte[]> css = new HashMap<String, byte[]>();
	//存放css的缓存
	private HashMap<String, byte[]> js = new HashMap<String, byte[]>();
	//存放image的缓存
	private HashMap<String, byte[]> image = new HashMap<String, byte[]>();
	
	
	//是否开发模式的标志,开发模式下会每次检查Web Module下的文件是否有，有的化使用web module下的
	private boolean devMode = false;
	
	/**
	 * Initialization of the servlet. <br>
	 *
	 * @throws ServletException if an error occure
	 */
	public void init() throws ServletException {
		
		devMode = "true".equals(this.getInitParameter("devMode"));
		
		String context = WebAppContextTag.getWebAppContext(this.getServletContext());
		StringBuffer header = new StringBuffer();
		try {
			//搜索accessory/css目录下所有的css文件,作为框架的css文件加载
			List<String> list = FileUtil.searchFileFromClassPath("com/guanghua/brick/html/accessory/css", ".*\\.css");
			logger.debug("start to search css file from brick jar");
			for (String path : list) {
				//从类路径中获取文件流
				InputStream is = BeanUtil.getClassPathFileByInputStream(path);
				String name = FileUtil.getFileName(path);
				//放入缓存map中
				css.put(name, readInputStreamAsByteArray(is));
				logger.trace("put css file [" + path + "] in accessory maps");
				
				//放入页面引用头
				header.append("<link type=\"text/css\" rel=\"stylesheet\" href=\"")
					.append(context)
					.append("/brick/css/")
					.append(name)
					.append("\"/>\n");
			}
		} catch (Exception e) {
			logger.error("find brick frame css wrong", e);
		}
		
		try {
			//搜索accessory/js目录下所有的js文件,作为框架的js文件加载
			List<String> list = FileUtil.searchFileFromClassPath("com/guanghua/brick/html/accessory/js", ".*\\.js");
			logger.debug("start to search js file from brick jar");
			for (String path : list) {
				//从类路径中获取文件流
				InputStream is = BeanUtil.getClassPathFileByInputStream(path);
				String name = FileUtil.getFileName(path);
				//放入缓存map中
				js.put(name, readInputStreamAsByteArray(is));
				logger.trace("put js file [" + path + "] in accessory maps");
				
				//放入页面引用头
				header.append("<script language=\"javascript\" src=\"")
				.append(context)
				.append("/brick/js/")
				.append(name)
				.append("\"></script>\n");
			}
		} catch (Exception e) {
			logger.error("find brick frame js wrong", e);
		}
		
		
		try {
			//搜索accessory/image目录下所有的gif文件,作为框架的gif文件加载
			List<String> list = FileUtil.searchFileFromClassPath("com/guanghua/brick/html/accessory/image", ".*\\.gif");
			logger.debug("start to search image file from brick jar");
			for (String path : list) {
				//从类路径中获取文件流
				InputStream is = BeanUtil.getClassPathFileByInputStream(path);
				String name = FileUtil.getFileName(path);
				//放入缓存map中
				image.put(name, readInputStreamAsByteArray(is));
				logger.trace("put image file [" + path + "] in accessory maps");
			}
		} catch (Exception e) {
			logger.error("find brick frame image wrong", e);
		}
		
		//将header放入servletcontext
		this.getServletContext().setAttribute(Constant.WEB_BRICK_HEAD, header.toString());
		
		try {
			//获取web/brick的目录，返回null是war包,以下跳过
			if (this.getServletContext().getRealPath("/brick") != null) {
				
				//搜索accessory下的jsp文件，覆盖的web目录下的jsp文件
				List<String> list = FileUtil.searchFileFromClassPath("com/guanghua/brick/html/accessory", ".*\\.jsp");
				logger.debug("start to search jsp file from brick jar");
				for (String path : list) {
					//从类路径中获取文件流
					InputStream is = BeanUtil.getClassPathFileByInputStream(path);
					byte[] content = readInputStreamAsByteArray(is);
					String name = FileUtil.getFileName(path);
					File file = new File(this.getServletContext().getRealPath("/brick/" + name));
					
					//文件不存在,建立文件
					if (!file.exists()) {
						//目录是否存在，不存在新建
						if (!file.getParentFile().exists())
							file.getParentFile().mkdirs();
						file.createNewFile();
					}
					
					FileOutputStream fos = new FileOutputStream(file);
					fos.write(content);
					fos.close();
					logger.trace("put jsp file [" + path + "] in web module brick dir");
					
				}
			}
			
		} catch (Exception e) {
			logger.error("find brick frame jsp and overwrite it wrong", e);
		}
	}
	
	/**
	 * Destruction of the servlet. <br>
	 */
	public void destroy() {
		css.clear();
		js.clear();
		image.clear();
	}
	
	/**
	 * The doGet method of the servlet. <br>
	 *
	 * This method is called when a form has its tag value method equals to get.
	 * 
	 * @param request the request send by the client to the server
	 * @param response the response send by the server to the client
	 * @throws ServletException if an error occurred
	 * @throws IOException if an error occurred
	 */
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String filePath = request.getServletPath() + request.getPathInfo();
		logger.trace("to request brick frame file servlet path [" + filePath + "]");
		//处理js/css/ui下的css文件
		if (filePath.startsWith("/brick/css/ui") && filePath.endsWith("css")) {
			dealCssFile(filePath, request, response);
		
		//处理js/css/ui下的css文件
		} else if (filePath.startsWith("/brick/js/frm_ui") && filePath.endsWith("js")) {
			dealJsFile(filePath, request, response);
			
		//处理image
		} else if (filePath.startsWith("/brick/image") && filePath.endsWith("gif")) {
			dealImageFile(filePath, request, response);
		}
	}
	
	
	/**
	 * 处理css file的方法。
	 * @param filePath
	 * @param request
	 * @param response
	 * @throws IOException 
	 * @throws ServletException 
	 */
	private void dealCssFile(String filePath, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		byte[] content;		
		//如果该文件不存在或者不是开发模式，直接使用jar包里的文件
		if (!this.devMode || !new File(this.getServletContext().getRealPath(filePath)).exists()) {
			//获取css content
			logger.trace("brick frame css file [" + filePath + "] not exist, use it in jar");
			content = css.get(FileUtil.getFileName(filePath));
		
		} else {
		//如果存在，那么返回web 目录中的文件
			logger.trace("brick frame css file [" + filePath + "] exist, use it in web module");
			FileInputStream fis = new FileInputStream(new File(this.getServletContext().getRealPath(filePath)));
			content = readInputStreamAsByteArray(fis);
		}
		
		response.setContentType("text/css");
		flush(content, response);
	}

	private void dealJsFile(String filePath, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		byte[] content;
		
		//如果该文件不存在或者不是开发模式，直接使用jar包里的文件
		if (!this.devMode || !new File(this.getServletContext().getRealPath(filePath)).exists()) {
			//获取css content
			logger.trace("brick frame js file [" + filePath + "] not exist, use it in jar");
			content = js.get(FileUtil.getFileName(filePath));

		
		} else {
		//如果存在，那么返回web 目录中的文件
			logger.trace("brick frame js file [" + filePath + "] exist, use it in web module");
			FileInputStream fis = new FileInputStream(new File(this.getServletContext().getRealPath(filePath)));
			content = readInputStreamAsByteArray(fis);
		}
		
		response.setContentType("text/javascript");
		flush(content, response);
	}

	
	private void dealImageFile(String filePath, HttpServletRequest request, HttpServletResponse response) throws IOException {
		byte[] content;
		
		//如果该文件不存在或者不是开发模式，直接使用jar包里的文件
		if (!this.devMode || !new File(this.getServletContext().getRealPath(filePath)).exists()) {
			//获取css content
			logger.trace("brick frame image file [" + filePath + "] not exist, use it in jar");
			content = image.get(FileUtil.getFileName(filePath));
		
		} else {
		//如果存在，那么返回web 目录中的文件
			logger.trace("brick frame image file [" + filePath + "] exist, use it in web module");
			FileInputStream fis = new FileInputStream(new File(this.getServletContext().getRealPath(filePath)));
			content = readInputStreamAsByteArray(fis);
		}
		
		response.setContentType("text/gif");
		flush(content, response);
		
	}
		
	/**
	 * flush流的方法
	 * @param content
	 * @param response
	 * @throws IOException
	 */
//	private void flush(String content, HttpServletResponse response) throws IOException {
//		//response.setHeader("Cache-Control", "no-cache");
//		//response.setCharacterEncoding("UTF-8");
//		PrintWriter out = response.getWriter();
//		out.print(content);
//		out.flush();
//		out.close();	
//	}
	
	/**
	 * flush流的方法
	 * @param content
	 * @param response
	 * @throws IOException
	 */
	private void flush(byte[] content, HttpServletResponse response) throws IOException {
		ServletOutputStream out = response.getOutputStream();
		if (content != null) out.write(content);
		out.flush();
		out.close();	
	}
	
	
	
//	protected void flush(InputStream is, HttpServletResponse response) throws IOException {
//		response.setContentType("application");
//		ServletOutputStream out = response.getOutputStream();
//		
//		int len = -1;
//		byte[] buf = new byte[4096];
//		
//		while((len = is.read(buf)) != -1) {
//			out.write(buf, 0, len);
//		}
//		
//		out.flush();
//		out.close();
//	}
	
		
	/**
	 * 读取inputstream成 string的方法
	 * @param is
	 * @return
	 * @throws IOException
	 */
//	private String readInputStream(InputStream is) throws IOException {
//		BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
//		StringBuffer sb = new StringBuffer();
//		
//		String s = null;
//		while ((s = br.readLine()) != null) {
//			sb.append(s).append("\n");
//		}
//		
//		br.close();
//		is.close();
//		return sb.toString();
//	}
	
	/**
	 * 读取inputstream成 byte array的方法
	 * @param is
	 * @return
	 * @throws IOException
	 */
	private byte[] readInputStreamAsByteArray(InputStream is) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		
		int len = -1;
		byte[] buf = new byte[4096];
		while((len = is.read(buf)) != -1) {
			baos.write(buf, 0, len);
		}
		
		byte[] ret = baos.toByteArray();
		is.close();
		baos.close();

		return ret;
	}
	
	 

}
